#include "DialogSelectScreen.h"
#include "ui_DialogSelectScreen.h"
#include <QFileDialog>
#include "VideoSynthesizer.h"
#include <QPainter>

DialogSelectScreen::DialogSelectScreen(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogSelectScreen)
{
    ui->setupUi(this);
    Qt::WindowFlags flags = (Qt::Window | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    //Qt::WindowFlags flags = (Qt::Window | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint );

    this->setWindowFlags(flags);
    setMouseTracking(true);
    ui->widgetTools->hide();
    ui->widgetInfo->hide();

    this->activateWindow();

    QRect fullScr = ScreenLayer::screenBound();
    m_screenSize = fullScr.size();
    for(QScreen *screen :  QApplication::screens())
    {
        QRect geometry = screen->geometry();
        qreal ratio = screen->devicePixelRatio();
        QRect physical_geometry(geometry.x(), geometry.y(),
                                static_cast<int32_t>(lrint(geometry.width() * ratio)),
                                static_cast<int32_t>(lrint(geometry.height() * ratio)));
        if(physical_geometry.contains(fullScr.center()))
        {
            setMainScale(ratio);

            fullScr = QRect(
                        static_cast<int32_t>(lrint((fullScr.x()) / ratio)),
                        static_cast<int32_t>(lrint((fullScr.y()) / ratio)),
                        static_cast<int32_t>(lrint(fullScr.width() / ratio)),
                        static_cast<int32_t>(lrint(fullScr.height() / ratio)));
            break;
        }
    }
    qInfo() << "m_mainScale=" <<m_mainScale;
    fullScr.setWidth(fullScr.width());

    this->setGeometry(fullScr);
    //if ( VideoSynthesizer::instance().openGlIsOK() )
    if (m_enableOpenGL)
    {
        ui->widget->setGeometry(fullScr);
    }
    else
    {
        QRect r = ui->widgetTools->geometry();
        ui->widgetTools->setParent(this);
        ui->widgetTools->setGeometry(r);
        //ui->widgetTools->show();

        r = ui->widgetInfo->geometry();
        ui->widgetInfo->setParent(this);
        ui->widgetInfo->setGeometry(r);
        //ui->widgetInfo->show();
        ui->widget->hide();

    }
    ui->widgetTools->setCursor(Qt::ArrowCursor);
    //connect(ui->widget, &GlScreenSelect::selected, this, &DialogSelectScreen::on_widget_selected);
    //connect(ui->widget, &GlScreenSelect::selected, this, &DialogSelectScreen::on_widget_selected);

    m_lineColor = QColor(0, 174, 255, 255);
    //m_lineColor = QVector4D( 0, 174.0f/255.0f, 1.0f, 1.0f );
    m_boxEditing = false;
    m_infoHide = true;
    setMouseTracking(true);

    ScreenLayer::fullScreenImage(m_imgScreen);
    m_imgDark = m_imgScreen;
    uint8_t* buf = m_imgDark.bits();
    uint8_t* bufEnd = buf + m_imgDark.byteCount();
    while( buf != bufEnd)
    {
        *buf++ >>= 1;
    }

    m_infoHide = false;
    getMouseOnWindow();

}

DialogSelectScreen::~DialogSelectScreen()
{
    if (m_repairTimerId)
    {
        killTimer(m_repairTimerId);
        m_repairTimerId = 0;
    }
    setMouseTracking(false);
    releaseKeyboard();
    delete ui;
}

void DialogSelectScreen::setMainScale(qreal scale)
{
    m_mainScale = scale;
    m_edgeSize = static_cast<int32_t>(lrint(m_edgeSize * m_mainScale - 1.0) / 2 * 2 + 1);

    QSize zoomBox( static_cast<int32_t>(lrint(4 * m_mainScale) * 29), static_cast<int32_t>(lrint(4 * m_mainScale) * 21) );
    int32_t edge = static_cast<int32_t>(lrint(3 * m_mainScale));
    m_InfoBox.setRect(0, 0, zoomBox.width() + edge * 2, zoomBox.height() + edge * 2);
    m_whiteBox = m_InfoBox.adjusted(1, 1, -1, -1);
    m_zoomBox.setRect(edge, edge, zoomBox.width(), zoomBox.height());

    m_fontSize = static_cast<int32_t>(lrint(16 * m_mainScale));
    m_infoTexBox.setRect(m_zoomBox.x(), m_InfoBox.height(), m_zoomBox.width(), m_fontSize );
    m_InfoBox.setHeight(m_InfoBox.height() + m_fontSize * 2 + 4);

    m_imgInfo = QImage(m_InfoBox.size(), QImage::Format_ARGB32);

    m_font = font();
    m_font.setPixelSize(12);
    m_font.setBold(false);
    m_font.setItalic(false);
}

void DialogSelectScreen::timerEvent(QTimerEvent *event)
{
    if ( m_repairTimerId == event->timerId())
    {
        if (m_boxEditing)
        {

        }
        else
        {
            getMouseOnWindow();
        }
    }
    else if (m_infoTimerId ==event->timerId())
    {
        m_infoShowProg -= 10;
        ui->widgetInfo->setStyleSheet(QString("QWidget#widgetInfo{background-color: rgb(0, 0, 0, %1);}").arg(qMin(255,qMax(0,m_infoShowProg * 255 / 100))));
        if (m_infoShowProg <= 0)
        {
            killTimer(m_infoTimerId);
            ui->widgetInfo->hide();
        }
    }

}

void DialogSelectScreen::setInfoShow(const QString &info)
{
    m_infoShowProg = 400;
    ui->labelInfo->setText(info);
    int x = (width() - ui->widgetInfo->width()) / 2;
    int y = (height() - ui->widgetInfo->height()) / 2;
    ui->widgetInfo->move(x, y);
    ui->widgetInfo->setStyleSheet("QWidget#widgetInfo{background-color: rgb(0, 0, 0, 255);}");
    ui->widgetInfo->show();
    m_infoTimerId = startTimer(50);
}

void DialogSelectScreen::on_widget_selected(bool cancel)
{
    fprintf(stderr, "on_widget_selected : %d\n", cancel);
    if ( cancel )
        this->reject();
    else
        this->accept();
}

void DialogSelectScreen::on_widget_editing(bool ready, const QRect& box)
{
    if (ready)
    {
        switch(m_selOpt.mode)
        {
        case ScreenLayer::unspecified:
            ui->labelType->setText("无");
            ui->labelType->setToolTip("");
            break;
        case ScreenLayer::specScreen:
            ui->labelType->setPixmap(QPixmap(":/typeIconScreen.png"));
            ui->labelType->setToolTip("指定屏幕");
            break;
        case ScreenLayer::fullScreen:
            ui->labelType->setPixmap(QPixmap(":/typeIconAllScreen.png"));
            ui->labelType->setToolTip("所有屏幕");
            break;
        case ScreenLayer::rectOfScreen:
            ui->labelType->setPixmap(QPixmap(":/typeIconScreenArea.png"));
            ui->labelType->setToolTip("屏幕区域");
            break;
        case ScreenLayer::specWindow:
            ui->labelType->setPixmap(QPixmap(":/typeIconWindow.png"));
            ui->labelType->setToolTip("指定窗口");
            break;
        case ScreenLayer::clientOfWindow:
            ui->labelType->setPixmap(QPixmap(":/typeIconWndClient.png"));
            ui->labelType->setToolTip("窗口内容");
            break;

        }
        ui->labelSize->setText(QString("%1 x %2").arg(m_realBox.width()).arg(m_realBox.height()));

        //显示工具栏的位置，准备8个位置，按顺序检查在哪个位置能显示最多的内容，就显示在哪个位置。
        QRect tool(0, 0, ui->widgetTools->width(), ui->widgetTools->height());
        QPoint pos[8];
        int32_t offset = static_cast<int32_t>(4 * m_mainScale);
        pos[0].setX(box.right() - tool.width()); pos[0].setY(box.bottom() + offset);
        pos[1].setX(box.right() - tool.width() - offset); pos[1].setY(box.bottom() - offset - tool.height());
        pos[2].setX(box.right() - tool.width()); pos[2].setY(box.top() - offset - tool.height());
        pos[3].setX(box.right() - tool.width() - offset); pos[3].setY(box.top() + offset);

        pos[4].setX(box.left()); pos[4].setY(box.bottom() + offset);
        pos[5].setX(box.left() + offset); pos[5].setY(box.bottom() - offset - tool.height());
        pos[6].setX(box.left()); pos[6].setY(box.top() - offset - tool.height());
        pos[7].setX(box.left() + offset); pos[7].setY(box.top() + offset);

        int32_t maxArea = 0;
        QPoint selPos = pos[0];
        for ( int32_t i = 0; i < 8; ++i )
        {
            QRect sect;
            tool.moveTo(pos[i]);
            for(QScreen *screen : QApplication::screens())
            {
                QRect geometry = screen->geometry();
                geometry.moveLeft(static_cast<int32_t>(lrint(geometry.left() / m_mainScale)));
                geometry.moveTop(static_cast<int32_t>(lrint(geometry.top() / m_mainScale)));
                sect = geometry.intersected(tool);
                if (sect.width() * sect.height() > maxArea)
                {
                    maxArea = sect.width() * sect.height();
                    selPos = pos[i];
                    if ( sect.width() == tool.width() && sect.height() == tool.height() ) break;
                }
            }
            if ( sect.width() == tool.width() && sect.height() == tool.height() ) break;
            if ( box.height() - offset * 2 < tool.height() ) ++i;
        }
        ui->widgetTools->move(selPos);
        ui->widgetTools->show();
        ui->widget->setToolsBox(ui->widgetTools->geometry());
        ui->toolButtonSave->setEnabled(true);
    }
    else
    {
        ui->widgetTools->hide();
    }
}

void DialogSelectScreen::on_toolButtonOK_clicked()
{
    this->accept();
}

void DialogSelectScreen::on_toolButtonCancel_clicked()
{
    this->reject();
}

void DialogSelectScreen::on_toolButtonSave_clicked()
{
//    QFileDialog dlg(this);
//    dlg.setAcceptMode(QFileDialog::AcceptSave);
//    dlg.setFileMode(QFileDialog::AnyFile);
//    dlg.setWindowTitle("保存截图文件");
//    dlg.setNameFilter("Picture (*.jpg *.jpeg *.bmp *.png)");
//    static QString dir = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
//    dlg.setDirectory(dir);
//    Qt::WindowFlags flags = (Qt::Window | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
//    //Qt::WindowFlags flags = (Qt::Window | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint );

//    dlg.setWindowFlags(dlg.windowFlags() | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint);
//    dlg.exec();
    //dlg.setDefaultSuffix(".jpg")
//    QString file = QFileDialog::getSaveFileName(this, "Save", QString(), "Picture (*.jpg *.jpeg *.bmp *.png)");
//    if (!file.isEmpty())
//    {
//        ui->widget->saveSelectToFile(file);
//    }

    QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
    if (!path.endsWith('/')) path += "/";

    path.append(QString("截图 %1.png").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd[HH-mm-ss]")));
    if (saveSelectToFile(path))
    {
        ui->toolButtonSave->setEnabled(false);
        setInfoShow("截图已经存储到：" + path);
    }

}


void DialogSelectScreen::mousePressEvent(QMouseEvent *event)
{
    if ( event->button() == Qt::LeftButton )
    {
        m_pressKeyPos = ScreenLayer::mousePhysicalCoordinates();
        if ( m_boxEditing )
        {
            m_hitType = hitTest(m_pressKeyPos);
            if (m_hitType == Qt::NoSection)
            {
                m_infoHide = true;
            }
            else
            {
                QPoint repos = m_pressKeyPos;
                switch(m_hitType)
                {
                case Qt::LeftSection:
                    m_pressKeyPos.setX(m_realBox.left());
                    break;
                case Qt::RightSection:
                    m_pressKeyPos.setX(m_realBox.right());
                    break;
                case Qt::TopSection:
                    m_pressKeyPos.setY(m_realBox.top());
                    break;
                case Qt::BottomSection:
                    m_pressKeyPos.setY(m_realBox.bottom());
                    break;
                case Qt::TopLeftSection:
                    m_pressKeyPos = (m_realBox.topLeft());
                    break;
                case Qt::BottomRightSection:
                    m_pressKeyPos = (m_realBox.bottomRight());
                    break;
                case Qt::TopRightSection:
                    m_pressKeyPos = (m_realBox.topRight());
                    break;
                case Qt::BottomLeftSection:
                    m_pressKeyPos = (m_realBox.bottomLeft());
                    break;
                default:
                    break;
                }

                on_widget_editing(false, QRect());
                m_oldBox = m_realBox;
                m_infoHide = ( m_hitType == Qt::TitleBarArea );
                m_leftDown = true;
                editBoxWithMouse(repos);
            }
        }
        else
        {
        }
    }
}

void DialogSelectScreen::mouseReleaseEvent(QMouseEvent *event)
{
    QPoint pos = ScreenLayer::mousePhysicalCoordinates();

    if (m_boxEditing)
    {
        if (event->button() == Qt::LeftButton && m_leftDown)
        {
            //选择区域编辑过程中放开了左键，完成选区编辑。
            if ( m_oldBox != m_realBox )
            {
                m_selOpt.mode = ScreenLayer::rectOfScreen;
                m_selOpt.geometry = m_realBox;
                m_selOpt.margins = QMargins();
            }

            m_infoHide = true;
            m_leftDown = false;
            m_lastMovePos = QPoint(-1, -1);
            on_widget_editing(true, QRectF(m_realBox.left() / m_mainScale,
                                     m_realBox.top() / m_mainScale,
                                     m_realBox.width() / m_mainScale,
                                     m_realBox.height() / m_mainScale).toRect());
            if (m_enableOpenGL)
                update();
            else
                makeUpdateRects(true);
        }
        else if (event->button() == Qt::RightButton)
        {
            m_boxEditing = false;
            m_leftDown = false;
            m_infoHide = false;
            m_hitType = Qt::NoSection;
            m_selOpt.mode = ScreenLayer::unspecified;
            m_lastMovePos = QPoint(-1, -1);
            on_widget_editing(false, QRect());
            setCursor(Qt::PointingHandCursor);
            getMouseOnWindow();
        }
    }
    else
    {
        if (event->button() == Qt::LeftButton)
        {
            //在选择窗口的状态下，放开左键，选区即为窗口
            if ( m_hitType == Qt::NoSection )
            {
                m_oldBox = m_realBox;
                m_hitType = hitTest(pos);
                setHitCursor(m_hitType);
                m_boxEditing = true;
                m_infoHide = true;
                m_leftDown = false;
                QRegion rgn(rect());
                parentWidget()->setMask(rgn);
                on_widget_editing(true, QRectF(m_realBox.left() / m_mainScale,
                                         m_realBox.top() / m_mainScale,
                                         m_realBox.width() / m_mainScale,
                                         m_realBox.height() / m_mainScale).toRect());

                if (m_enableOpenGL)
                    update();
                else
                    makeUpdateRects(true);
            }
        }
        else if (event->button() == Qt::RightButton)
        {
            on_widget_selected(true);
        }
    }
}

void DialogSelectScreen::mouseMoveEvent(QMouseEvent *event)
{
    QPoint pos = ScreenLayer::mousePhysicalCoordinates();
    makePixelInfo(pos);
    if ( m_boxEditing )
    {
        if ( event->buttons() & Qt::LeftButton )
        {
            if ( m_hitType != Qt::NoSection )
            {
                editBoxWithMouse(pos);
            }
        }
        else
        {
            Qt::WindowFrameSection hit = hitTest(pos);
            if ( m_hitType != hit )
            {
                m_hitType = hit;
                setHitCursor(hit);
            }
        }
    }
    else
    {
        getMouseOnWindow();
        if ( event->buttons() & Qt::LeftButton )
        {
            //按下鼠标拖动一段距离，首次创建选择区域
            if ( abs(pos.x() - m_pressKeyPos.x()) >= 3 && abs(pos.y() - m_pressKeyPos.y()) >= 3 )
            {
                m_boxEditing = true;
                m_leftDown = true;
                m_infoHide = false;
                m_realBox = QRect(m_pressKeyPos, pos).normalized();
                m_oldBox = m_realBox;
                m_pressKeyPos = pos;
                m_selOpt.mode = ScreenLayer::rectOfScreen;
                m_selOpt.geometry = m_realBox;
                m_selOpt.margins = QMargins();
                m_hitType = hitTest(pos);
                setHitCursor(m_hitType);
                QRegion rgn(rect());
                parentWidget()->setMask(rgn);
                if (m_enableOpenGL)
                    update();
                else
                    makeUpdateRects(true);
            }
        }
    }
}

void DialogSelectScreen::keyPressEvent(QKeyEvent *event)
{
    fprintf( stderr, "event->key()=%d\n", event->key());
    if(event->key() == Qt::Key_Escape)
    {
        on_widget_selected(true);
    }
    else if(event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
    {
        on_widget_selected(false);
        return;
    }
    event->ignore();
}

void DialogSelectScreen::paintEvent(QPaintEvent *e)
{
    QPainter pnt;
    pnt.begin(this);

    QRectF rt(e->rect().left() * m_mainScale, e->rect().top() * m_mainScale, e->rect().width() * m_mainScale, e->rect().height() * m_mainScale);
    pnt.drawImage(e->rect(), m_imgDark, rt);

    QRect rtInfo;
    rtInfo.setLeft(qFloor(m_InfoBox.left() / m_mainScale));
    rtInfo.setTop( qFloor(m_InfoBox.top() / m_mainScale));
    rtInfo.setRight(qCeil(m_InfoBox.right() / m_mainScale));
    rtInfo.setBottom(qCeil(m_InfoBox.bottom() / m_mainScale));

    QRect rtClip = e->rect().intersected(rtInfo);
    if (rtClip.isValid() && !m_infoHide)
    {
        QRect rtSour = rtClip.translated(-rtClip.topLeft());
        rtSour.setLeft(qMax(0, qFloor(rtSour.left() * m_mainScale)));
        rtSour.setTop(qMax(0, qFloor(rtSour.top() * m_mainScale)));
        rtSour.setRight(qMin(m_InfoBox.right(), qCeil(rtSour.right() * m_mainScale)));
        rtSour.setBottom(qMin(m_InfoBox.bottom(), qCeil(rtSour.bottom() * m_mainScale)));
        pnt.drawImage(rtClip, m_imgInfo, rtSour);
    }



    pnt.end();
}

void DialogSelectScreen::enterEvent(QEvent *event)
{
    Q_UNUSED(event)

    //grabMouse();
    //grabKeyboard();
    //setCursor(Qt::BlankCursor);
    //setCursor(Qt::PointingHandCursor);
    setHitCursor(m_hitType);
    if (!m_boxEditing)
    {
        getMouseOnWindow();
    }
    if (m_repairTimerId == 0)
    {
        m_repairTimerId = startTimer(10);
    }
    //update();
}

void DialogSelectScreen::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event)
    on_widget_selected(false);
}


bool DialogSelectScreen::saveSelectToFile(const QString &filePath)
{
    QImage img = m_imgScreen.copy(m_realBox);
    return img.save(filePath, nullptr, 100);
}

void DialogSelectScreen::getMouseOnWindow()
{
    QPoint phyPos = ScreenLayer::mousePhysicalCoordinates();
    QPoint wndPos = phyPos / m_mainScale;
    bool needUpdate = false;
    if (phyPos != m_lastMovePos)
    {
        m_lastMovePos = phyPos;
        m_currMouseRect.setRect(wndPos.x() - 1, wndPos.y() - 1, 3, 3);
        needUpdate = true;
        makePixelInfo(m_lastMovePos);
    }

    ScreenLayer::Option opt = ScreenLayer::posOnWindow(phyPos, parentWidget()->winId());
//    qDebug() << "On" << opt.windowId << ",My" << this->winId() << ",Pa" << parentWidget()->winId();

    if ( opt.mode != m_selOpt.mode || opt.widTop != m_selOpt.widTop || opt.geometry != m_selOpt.geometry || opt.margins != m_selOpt.margins )
    {
        m_selOpt = opt;
        if ( opt.mode != ScreenLayer::unspecified )
        {
            m_realBox = opt.geometry + opt.margins;
        }
        else
        {
            m_realBox = QRect();
        }
        needUpdate = true;
    }
    if (needUpdate)
    {
        if (m_enableOpenGL)
            update();
        else
            makeUpdateRects(false);
    }

}

Qt::WindowFrameSection DialogSelectScreen::hitTest(const QPoint &pos)
{
    Qt::WindowFrameSection hit = Qt::NoSection;
    int32_t minLen = m_edgeSize / 2 + 1 + 1;
    QPoint corner;
    corner = m_realBox.bottomRight();
    if ( abs(corner.x() - pos.x()) < minLen && abs(corner.y() - pos.y()) < minLen )
    {
        hit = Qt::BottomRightSection;
        minLen = qMin(abs(corner.x() - pos.x()), abs(corner.y() - pos.y()));
    }
    corner = m_realBox.topRight();
    if ( abs(corner.x() - pos.x()) < minLen && abs(corner.y() - pos.y()) < minLen )
    {
        hit = Qt::TopRightSection;
        minLen = qMin(abs(corner.x() - pos.x()), abs(corner.y() - pos.y()));
    }
    corner = m_realBox.topLeft();
    if ( abs(corner.x() - pos.x()) < minLen && abs(corner.y() - pos.y()) < minLen )
    {
        hit = Qt::TopLeftSection;
        minLen = qMin(abs(corner.x() - pos.x()), abs(corner.y() - pos.y()));
    }
    corner = m_realBox.bottomLeft();
    if ( abs(corner.x() - pos.x()) < minLen && abs(corner.y() - pos.y()) < minLen )
    {
        hit = Qt::BottomLeftSection;
        minLen = qMin(abs(corner.x() - pos.x()), abs(corner.y() - pos.y()));
    }

    if (hit == Qt::NoSection)
    {
        int32_t  cl = 0;
        if ( pos.y() > m_realBox.top() && pos.y() < m_realBox.bottom() )
        {
            cl = abs(pos.x() - m_realBox.right());
            if ( cl < minLen )
            {
                hit = Qt::RightSection;
                minLen = cl;
            }
            cl = abs(pos.x() - m_realBox.left());
            if ( cl < minLen )
            {
                hit = Qt::LeftSection;
                minLen = cl;
            }
        }
        if ( pos.x() > m_realBox.left() && pos.x() < m_realBox.right() )
        {
            cl = abs(pos.y() - m_realBox.bottom());
            if ( cl < minLen )
            {
                hit = Qt::BottomSection;
                minLen = cl;
            }
            cl = abs(pos.y() - m_realBox.top());
            if ( cl < minLen )
            {
                hit = Qt::TopSection;
                minLen = cl;
            }
        }
    }

    if (hit == Qt::NoSection)
    {
        if ( pos.x() > m_realBox.left() && pos.x() < m_realBox.right() && pos.y() > m_realBox.top() && pos.y() < m_realBox.bottom() )
        {
            hit = Qt::TitleBarArea;
        }
    }
    return hit;
}

void DialogSelectScreen::setHitCursor(Qt::WindowFrameSection hit)
{
    switch(hit)
    {
    case Qt::LeftSection:
    case Qt::RightSection:
        setCursor(Qt::SizeHorCursor);
        break;
    case Qt::TopSection:
    case Qt::BottomSection:
        setCursor(Qt::SizeVerCursor);
        break;
    case Qt::TopLeftSection:
    case Qt::BottomRightSection:
        setCursor(Qt::SizeFDiagCursor);
        break;
    case Qt::TopRightSection:
    case Qt::BottomLeftSection:
        setCursor(Qt::SizeBDiagCursor);
        break;
    case Qt::TitleBarArea:
        setCursor(Qt::SizeAllCursor);
        break;
    default:
        setCursor(Qt::ArrowCursor);
        break;
    }
}

void DialogSelectScreen::editBoxWithMouse(const QPoint& pos)
{
    if (pos == m_lastMovePos || m_leftDown == false)
    {
        return;
    }
    m_lastMovePos = pos;
    int32_t x = pos.x();
    int32_t y = pos.y();
    int32_t l = m_oldBox.left();
    int32_t t = m_oldBox.top();
    int32_t r = m_oldBox.right();
    int32_t b = m_oldBox.bottom();
    Qt::WindowFrameSection hit = m_hitType;
    switch(m_hitType)
    {
    case Qt::TitleBarArea:
        if (!checkOffsetX(l,x))
        {
            r = l + m_realBox.width() - 1;
        }
        else
        {
            checkOffsetX(r, x);
            l = r - m_realBox.width() + 1;
        }
        if (!checkOffsetY(t, y))
        {
            b = t + m_realBox.height() - 1;
        }
        else
        {
            checkOffsetY(b, y);
            t = b - m_realBox.height() + 1;
        }
        break;
    case Qt::LeftSection:
        checkOffsetX(l,x);
        if (l > r)
        {
            swap(l,r);
            hit = Qt::RightSection;
        }
        break;
    case Qt::RightSection:
        checkOffsetX(r,x);
        if (l > r)
        {
            swap(l,r);
            hit = Qt::LeftSection;
        }
        break;
    case Qt::TopSection:
        checkOffsetY(t,y);
        if (t > b)
        {
            swap(t,b);
            hit = Qt::BottomSection;
        }
        break;
    case Qt::BottomSection:
        checkOffsetY(b,y);
        if (t > b)
        {
            swap(t,b);
            hit = Qt::TopSection;
        }
        break;
    case Qt::TopLeftSection:
        checkOffsetY(t,y);
        checkOffsetX(l,x);
        if ( t > b && l > r )
        {
            swap(l, r);
            swap(t, b);
            hit = Qt::BottomRightSection;
        }
        else if (t > b)
        {
            swap(t, b);
            hit = Qt::BottomLeftSection;
        }
        else if (l > r)
        {
            swap(l, r);
            hit = Qt::TopRightSection;
        }
        break;
    case Qt::TopRightSection:
        checkOffsetY(t,y);
        checkOffsetX(r,x);
        if ( t > b && l > r )
        {
            swap(l, r);
            swap(t, b);
            hit = Qt::BottomLeftSection;
        }
        else if (t > b)
        {
            swap(t, b);
            hit = Qt::BottomRightSection;
        }
        else if (l > r)
        {
            swap(l, r);
            hit = Qt::TopLeftSection;
        }
        break;
    case Qt::BottomLeftSection:
        checkOffsetY(b,y);
        checkOffsetX(l,x);
        if ( t > b && l > r )
        {
            swap(l, r);
            swap(t, b);
            hit = Qt::TopRightSection;
        }
        else if (t > b)
        {
            swap(t, b);
            hit = Qt::TopLeftSection;
        }
        else if (l > r)
        {
            swap(l, r);
            hit = Qt::BottomRightSection;
        }
        break;
    case Qt::BottomRightSection:
        checkOffsetY(b,y);
        checkOffsetX(r,x);
        if ( t > b && l > r )
        {
            swap(l, r);
            swap(t, b);
            hit = Qt::TopLeftSection;
        }
        else if (t > b)
        {
            swap(t, b);
            hit = Qt::TopRightSection;
        }
        else if (l > r)
        {
            swap(l, r);
            hit = Qt::BottomLeftSection;
        }
        break;
    default:
        return;
    }
    m_realBox.setRect(l, t, r - l + 1, b - t + 1);
    m_selOpt.geometry = m_realBox;
    if ( m_hitType != hit )
    {
        m_hitType = hit;
        setHitCursor(hit);
        m_pressKeyPos = pos;
        m_oldBox = m_realBox;
    }
    if (m_enableOpenGL)
        update();
    else
        makeUpdateRects(false);
}

void DialogSelectScreen::makeUpdateRects(bool force)
{
    auto rectSub = [=](QRect org, QRect sub, QVector<QRect>& lst){
        if (!sub.isValid())
        {
            lst.append(org);
            return;
        }
        if (org.isValid() && sub.isValid() && org.y() < sub.y())
        {
            int y = qMin(org.bottom() + 1, sub.y());
            lst.append(QRect(org.x(), org.y(), org.width(), y - org.y()));
            org.setY(y);
        }
        if (org.isValid() && sub.isValid() && org.bottom() > sub.bottom())
        {
            int y = qMax(org.y() - 1, sub.bottom());
            lst.append(QRect(org.x(), y + 1, org.width(), org.bottom() - y));
            org.setBottom(y);
        }
        if (org.isValid() && sub.isValid() && org.x() < sub.x())
        {
            int x = qMin(org.right() + 1, sub.x());
            lst.append(QRect(org.x(), org.y(), x - org.x(), org.height()));
            org.setX(x);
        }
        if (org.isValid() && sub.isValid() && org.right() > sub.right())
        {
            int x = qMax(org.x() - 1, sub.right());
            lst.append(QRect(x + 1, org.y(), org.right() - x, org.height()));
            org.setRight(x);
        }
    };

    QVector<QRect> rects;
    QVector<QRect> rectDraws;
    int32_t minLen = m_edgeSize / 2 + 1 + 1;
    QMargins marg(minLen, minLen, minLen, minLen);
    if (m_prevDrawBox != m_realBox || force)
    {
        if (m_prevDrawBox.isValid())
        {
            rectSub(m_imgDark.rect().intersected(m_prevDrawBox + marg), m_imgDark.rect().intersected(m_realBox), rects);
        }
        rectDraws << rects;
        for (auto& r : rects)
        {
            uint8_t* bufDrak = m_imgDark.scanLine(r.top()) + r.left() * 3;
            uint8_t* bufNomr = m_imgScreen.scanLine(r.top()) + r.left() * 3;
            int skip = m_imgDark.bytesPerLine() - r.width() * 3;
            for (int y = r.top(); y <= r.bottom(); ++y )
            {
                for (int x = r.left(); x <= r.right(); ++x)
                {
                    bufDrak[0] = bufNomr[0] >> 1;
                    bufDrak[1] = bufNomr[1] >> 1;
                    bufDrak[2] = bufNomr[2] >> 1;
                    bufDrak += 3;
                    bufNomr += 3;
                }
                bufDrak += skip;
                bufNomr += skip;
            }
        }
        rects.clear();
        rectSub(m_imgDark.rect().intersected(m_realBox), m_prevDrawBox - marg, rects);
        rectDraws << rects;
        for (auto& r : rects)
        {
            uint8_t* bufDrak = m_imgDark.scanLine(r.top()) + r.left() * 3;
            uint8_t* bufNomr = m_imgScreen.scanLine(r.top()) + r.left() * 3;
            int skip = m_imgDark.bytesPerLine() - r.width() * 3;
            for (int y = r.top(); y <= r.bottom(); ++y )
            {
                for (int x = r.left(); x <= r.right(); ++x)
                {
                    bufDrak[0] = bufNomr[0];
                    bufDrak[1] = bufNomr[1];
                    bufDrak[2] = bufNomr[2];
                    bufDrak += 3;
                    bufNomr += 3;
                }
                bufDrak += skip;
                bufNomr += skip;
            }
        }
        rects.clear();
        m_prevDrawBox = m_realBox;
        QPainter pnt(&m_imgDark);
        QPen pen(m_lineColor);
        if (m_boxEditing)
        {
            pen.setWidth(1);
            pnt.setPen(pen);
            pnt.drawRect(QRect(m_realBox.topLeft(), m_realBox.bottomRight() - QPoint(1,1)));

            pnt.fillRect( m_realBox.x() - m_edgeSize / 2, m_realBox.y() + m_realBox.height() / 2 - m_edgeSize / 2, m_edgeSize, m_edgeSize, m_lineColor);
            pnt.fillRect( m_realBox.right() - m_edgeSize / 2, m_realBox.y() + m_realBox.height() / 2 - m_edgeSize / 2, m_edgeSize, m_edgeSize, m_lineColor);
            pnt.fillRect( m_realBox.x() + m_realBox.width() / 2 - m_edgeSize / 2, m_realBox.y() - m_edgeSize / 2, m_edgeSize, m_edgeSize, m_lineColor);
            pnt.fillRect( m_realBox.x() + m_realBox.width() / 2 - m_edgeSize / 2, m_realBox.bottom() - m_edgeSize / 2, m_edgeSize, m_edgeSize, m_lineColor);

            pnt.fillRect( m_realBox.x() - m_edgeSize / 2, m_realBox.y() - m_edgeSize / 2, m_edgeSize, m_edgeSize, m_lineColor);
            pnt.fillRect( m_realBox.x() - m_edgeSize / 2, m_realBox.bottom() - m_edgeSize / 2, m_edgeSize, m_edgeSize, m_lineColor);

            pnt.fillRect( m_realBox.right() - m_edgeSize / 2, m_realBox.y() - m_edgeSize / 2, m_edgeSize, m_edgeSize, m_lineColor);
            pnt.fillRect( m_realBox.right() - m_edgeSize / 2, m_realBox.bottom() - m_edgeSize / 2, m_edgeSize, m_edgeSize, m_lineColor);
        }
        else
        {
            pen.setWidth(m_edgeSize);
            pnt.setPen(pen);
            pnt.drawRect(QRect(m_realBox.topLeft(), m_realBox.bottomRight() - QPoint(1,1)));
        }
        rectSub(m_imgDark.rect().intersected(m_realBox + marg), m_imgDark.rect().intersected(m_realBox - marg), rects);
        rectDraws << rects;
        rects.clear();

    }
    if (m_infoHide)
    {
        if (force)
        {
            rectDraws << m_InfoBox;
        }
    }
    else
    {
        QRect oldRect = m_InfoBox;
        QPointF offset(ceil(6 * m_mainScale), ceil(24 * m_mainScale));

        for ( int32_t i = 0; i < ScreenLayer::screenCount(); ++i)
        {
            QRect geometry = ScreenLayer::screenRect(i);
            if ( geometry.contains(m_lastMovePos) )
            {
                if ( m_lastMovePos.y() + offset.y() + m_InfoBox.height() > geometry.bottom() )
                {
                    offset.setY( -(offset.y() + m_InfoBox.height()) );
                }
                if ( m_lastMovePos.x() + offset.x() + m_InfoBox.width() > geometry.right() )
                {
                    offset.setX( -(offset.x() + m_InfoBox.width()) );
                }
            }
        }

        m_InfoBox.moveTo(offset.toPoint() + m_lastMovePos);
        //oldRect.adjust(-1, -1, 1, 1);
        rectSub(oldRect, m_InfoBox, rectDraws);
        rectDraws << m_InfoBox;
    }
    for (auto& r : rectDraws)
    {
        if (qAbs(m_mainScale - 1.0) > 0.01)
        {
            QRect rt;
            rt.setLeft(qFloor(r.left() / m_mainScale));
            rt.setTop( qFloor(r.top() / m_mainScale));
            rt.setRight(qCeil(r.right() / m_mainScale));
            rt.setBottom(qCeil(r.bottom() / m_mainScale));
            repaint(rt);
        }
        else
        {
            repaint(r);
        }
    }
}

void DialogSelectScreen::makePixelInfo(const QPoint &pos)
{
    m_imgInfo.fill(QColor(0, 0, 0, 255 * 8 / 10));
    QPainter pnt;
    pnt.begin(&m_imgInfo);
    pnt.fillRect(m_whiteBox, QColor(255, 255, 255));

    QImage zoomImg = m_imgScreen.copy(QRect(pos.x() - 14, pos.y() - 10, 29, 21));
    uint8_t* pix = zoomImg.scanLine(10);
    for ( int x = 0; x < 29; ++x)
    {
        pix[0] = (m_lineColor.red() + pix[0]) >> 1;
        pix[1] = (m_lineColor.green() + pix[1]) >> 1;
        pix[2] = (m_lineColor.blue() + pix[2]) >> 1;
        pix += 3;
    }
    pix = zoomImg.bits() + 14 * 3;
    for ( int y = 0; y < 21; ++y)
    {
        pix[0] = (m_lineColor.red() + pix[0]) >> 1;
        pix[1] = (m_lineColor.green() + pix[1]) >> 1;
        pix[2] = (m_lineColor.blue() + pix[2]) >> 1;
        pix += zoomImg.bytesPerLine();
    }
    pnt.drawImage(m_zoomBox, zoomImg);

    pnt.setFont(m_font);
    QRectF draw = m_infoTexBox;//(m_infoTexBox.x() / m_mainScale, m_infoTexBox.y() / m_mainScale, m_infoTexBox.width() / m_mainScale, m_infoTexBox.height() / m_mainScale);
    pnt.setPen(Qt::white);
    pnt.drawText(draw, Qt::AlignLeft | Qt::AlignVCenter, QString("%1 x %2").arg(m_realBox.width()).arg(m_realBox.height()));
    draw.adjust(0, m_fontSize / m_mainScale, 0, m_fontSize / m_mainScale);
    QColor co = m_imgScreen.pixelColor(pos);
    pnt.drawText(draw, Qt::AlignLeft | Qt::AlignVCenter, QString("RGB:(%1,%2,%3)").arg(co.red()).arg(co.green()).arg(co.blue()));

    pnt.end();
}



